package cn.sytton.taffe.log.service.impl;

import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.sytton.taffe.log.entity.ApiLogEntity;
import cn.sytton.taffe.log.mapper.ApiLogMapper;
import cn.sytton.taffe.framework.log.ILogRecord;
import cn.sytton.taffe.framework.request.RequestStreamHelper;
import cn.sytton.taffe.framework.response.ResponseResult;
import cn.sytton.taffe.framework.util.SecurityUtil;
import cn.sytton.taffe.framework.util.JsonUtil;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.Date;

/**
 * Api访问日志记录接口实现类
 *
 * @author skyrock
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class LogRecord implements ILogRecord {

    private final ApiLogMapper apiLogMapper;

    @Override
    public String begin(Method method, HttpServletRequest request, Object handler) {

        String arg = request.getQueryString();
        if (arg == null || "null".equals(arg)) {
            arg = "";
        } else if (StringUtils.hasText(arg)) {
            arg = "[query]:"+arg;
        }
        if ("POST".equalsIgnoreCase(request.getMethod())) {
            if ("application/json".equals(request.getContentType())){
                arg += "[body]:"+ RequestStreamHelper.getBodyString(request);
            }
        }
        ApiLogEntity logEntity = new ApiLogEntity();
        if (SecurityUtil.isLogin()) {
            logEntity.setUserId(SecurityUtil.getUserId());
            logEntity.setLoginName(SecurityUtil.getLoginName());
            logEntity.setUserCode(SecurityUtil.getUserCode());
            logEntity.setUserName(SecurityUtil.getUserName());
        }
        logEntity.setAccessSource("pc"); //todo 设置访问来源
        logEntity.setUrl(request.getRequestURI());
        logEntity.setRequestMethod(request.getMethod());
        logEntity.setMethod(method.getDeclaringClass().getName()+"."+method.getName());
        Operation apiOperation = method.getAnnotation(Operation.class);
        if (apiOperation != null) {
            logEntity.setMethodName(apiOperation.summary());
        }
        logEntity.setParams(arg.length() > 2047 ? arg.substring(0, 2047) : arg);
        logEntity.setIp(ServletUtil.getClientIP(request));
        logEntity.setLocation(""); //todo 设置访问位置
        UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
        if (userAgent != null) {
            logEntity.setOs(userAgent.getOs().getName());
            logEntity.setBrowser(userAgent.getBrowser().getName());
        }
        logEntity.setBeginTime(new Timestamp(new Date().getTime()));
        return JsonUtil.getString(logEntity);
    }

    @Override
    public void end(String data, Object result) {
        ApiLogEntity logEntity = JsonUtil.getEntity(data, ApiLogEntity.class);
        if (logEntity != null) {
            ResponseResult resp;
            if (result instanceof ResponseResult){
                resp = (ResponseResult) result;
            } else {
                resp = ResponseResult.success(result);
            }
            logEntity.setEndTime(new Timestamp(new Date().getTime()));
            logEntity.setSuccess(resp.isSuccess());
            logEntity.setErrMsg(resp.isSuccess() ? "" : resp.getMessage());
            String respData = JsonUtil.getString(resp);
            logEntity.setResult(respData.length() > 2047 ? respData.substring(0, 2047) : respData);
            apiLogMapper.insert(logEntity);
        }
    }
}
